package cgl.sensorgrid.sopac.gps.filters;

import java.util.*;

import cgl.narada.event.*;
import cgl.sensorgrid.filters.*;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import cgl.sensorgrid.common.PropertyFile;
import java.text.SimpleDateFormat;
import java.io.*;

import org.apache.log4j.Logger;

class RunRdahmm1 {

	private Object syncObj1 = new Object();

	private List eventList = Collections.synchronizedList(new LinkedList());

	private String evalDir;

	private String dataDir;

	private String rdahmmshellDir;

	private String plotshellDir;

	private String NetworkName;

	private java.util.Properties properties = new java.util.Properties();

	private int noOfObservations;

	static long runcount = 0;

	private Hashtable ht = new Hashtable();

	public RunRdahmm1() {
	}

	public RunRdahmm1(String[] argsb) {
		loadProperties();
		evalDir = properties.getProperty("rdahmm.eval.directory");
		dataDir = properties.getProperty("rdahmm.data.directory");
		rdahmmshellDir = properties.getProperty("rdahmm.rdahmmshell.directory");
		plotshellDir = properties.getProperty("rdahmm.plotshell.directory");
		System.out.println("[RdahmmFilter] --> Rdahmm Application Directory = "
				+ evalDir);
		System.out.println("[RdahmmFilter] --> Rdahmm Data Directory = "
				+ dataDir);
		// {siteName, noOfObservations, rdahmmMode};
		if (argsb.length == 2) {
			if (argsb[0] != null && argsb[0].length() > 0) {
				this.noOfObservations = Integer.parseInt(argsb[0]);
				this.NetworkName = argsb[1];
//				this.dataDir = dataDir + "/" + NetworkName;
//				this.evalDir = evalDir + "/" + NetworkName;
				System.out
						.println("[SaveNetwork] --> # Of Observations per file = "
								+ this.noOfObservations);
			}
		}
	}

	/**
	 * 
	 * @return Properties
	 */
	private java.util.Properties loadProperties() {
		// Read properties file.
		try {
			properties = PropertyFile.loadProperties("sensorgrid.properties");
		} catch (Exception e) {
			e.printStackTrace();
		}
		return properties;
	}

	/**
	 * 
	 * @param event
	 *            NBEvent
	 */
	public void addEvent(NBEvent event) {
		synchronized (syncObj1) {
			eventList.add(event);
			if (eventList.size() == 1) {
				syncObj1.notify();
			}
		}
	}

	/**
	 * 
	 * @param event
	 *            NBEvent
	 */
	public void run() {
		boolean running = true;
		try {
			while (running) {
				synchronized (syncObj1) {
					if (eventList.size() == 0) {
						syncObj1.wait();
					}
					NBEvent nbEvent = (NBEvent) eventList.remove(0);
					byte[] data2 = nbEvent.getContentPayload();
					if (data2 != null && data2.length > 0) {
						processMessage(new String(data2));
					}
				}
			}
			return;
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

	static int eventcount = 0;

	public void processMessage(String msg) {
		try {
			StringTokenizer st = new StringTokenizer(msg, "\n");
			while (st.hasMoreTokens()) {
				String token = st.nextToken();
				if (!token.startsWith("EOF")) {
					if (token.length() > 4) {
						String station = token.substring(0, 4);
						if (ht.get(station) != null) {
							RdahmmDataStruct rd = (RdahmmDataStruct) ht
									.get(station);
							rd.addLine(token + "\n");
						} else {
							RdahmmDataStruct rd = new RdahmmDataStruct(
									noOfObservations, dataDir, evalDir,
									rdahmmshellDir, plotshellDir);
							rd.setSiteName(station);
							ht.put(station, rd);
						}
					}
				}
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

	public String getDate(long timeinms) {
		Calendar cal = Calendar.getInstance();
		cal.setTimeInMillis(timeinms);
		SimpleDateFormat myDateFormat = new SimpleDateFormat(
				"yyyy_MM_dd-hh_mm_ss_a");
		return myDateFormat.format(cal.getTime());
	}
}

/**
 * 
 * <p>
 * Title: SensorGrid
 * </p>
 * 
 * <p>
 * Description:
 * </p>
 * 
 * <p>
 * Copyright: Copyright (c) 2006
 * </p>
 * 
 * <p>
 * Company:
 * </p>
 * 
 * @author Galip Aydin
 * @version 1.0
 */
public class RdahmmRunner extends Filter {
	public RdahmmRunner() {
	}

	private RunRdahmm1 r2a;

	static Logger logger = Logger.getLogger(SimpleFilter.class.getName());

	public RdahmmRunner(String[] args, String[] argsb) {
		if (args == null || args.length == 0) {
			System.err
					.println("Incorrect number of arguments in ryo2ascii::Constructor...");
		} else {
			this.initialize(args);
			r2a = new RunRdahmm1(argsb);
			r2a.run();
		}
	}

	public void onEvent(NBEvent nbEvent) {
		if (nbEvent.getContentPayload() != null) {
			if (r2a != null && nbEvent != null) {
				r2a.addEvent(nbEvent);
			}
		}
	}

	/**
	 * Execute a command
	 * 
	 * @param execStr
	 *            String command string
	 * @return String the information of execute result
	 */
	public static String exec(String execStr) {
		Runtime runtime = Runtime.getRuntime();// Get current runtime object
		String outInfo = ""; // execute error information
		try {
			String osname = System.getProperty("os.name");
			String[] args = null;
			if (osname.equals("Linux")) {
				args = new String[] { "sh", "-c", execStr }; // execute
				// linux command
			} else if (osname.substring(0, 3).equals("Win")) {
				args = new String[] { "cmd", "/c", execStr }; // execute
			} else {
				System.exit(0);
			}

			Process proc = runtime.exec(args); // run another process to
			// execute command
			InputStream out = proc.getInputStream();
			BufferedReader br1 = new BufferedReader(new InputStreamReader(out));
			while (br1.readLine() != null) {
			}
			out.close();

			InputStream in = proc.getErrorStream(); // get error information
			BufferedReader br = new BufferedReader(new InputStreamReader(in));
			String line = "";
			while ((line = br.readLine()) != null) {
				outInfo = outInfo + line + "/n";
			}
			// System.out.println(outInfo);
			in.close();

			try { // check the result
				if (proc.waitFor() != 0) {
					System.err.println("exit value = " + proc.exitValue());
				}
			} catch (InterruptedException e) {
				System.err.print(e);
				e.printStackTrace();
			}

		} catch (IOException e) {
			System.out.println("exec error: " + e.getMessage());
			e.printStackTrace();
		}
		return outInfo;
	}

	public static void WriteFile(String Wfilename, String Wmessage,
			boolean Wtype) {
		try {
			BufferedWriter out = new BufferedWriter(new FileWriter(Wfilename,
					Wtype));
			out.write(Wmessage);
			out.close();
		} catch (IOException e) {
			logger.error("got an IOException error!");
			e.printStackTrace();
		}
	}

	public static String ReadFile(String Rfilename) {
		String Rmessage = "";
		try {
			String record = null;
			BufferedReader out = new BufferedReader(new FileReader(Rfilename));
			record = new String();
			while ((record = out.readLine()) != null) {
				Rmessage = Rmessage + record + "\n";
				record = "";
			}
			out.close();
		} catch (IOException e) {
			logger.error("got an IOException error!");
			e.printStackTrace();
		}
		return Rmessage;
	}

	public static void copyfile(String srFile, String dtFile) {
		try {
			File f1 = new File(srFile);
			File f2 = new File(dtFile);
			InputStream in = new FileInputStream(f1);

			// For Append the file.
			// OutputStream out = new FileOutputStream(f2,true);

			// For Overwrite the file.
			OutputStream out = new FileOutputStream(f2);

			byte[] buf = new byte[1024];
			int len;
			while ((len = in.read(buf)) > 0) {
				out.write(buf, 0, len);
			}
			in.close();
			out.flush();
			out.close();
			System.out.println("File copied.");
		} catch (FileNotFoundException ex) {
			System.out
					.println(ex.getMessage() + " in the specified directory.");
			System.exit(0);
		} catch (IOException e) {
			System.out.println(e.getMessage());
		}
	}

	public static void main(String args[]) {
		if (args.length < 5) {
			System.out
					.println("Usage: java cgl.sensorgrid.sopac.gps.filters.RdahmmFilter commType nbHost nbPort subTopic noOfObservations");
			System.exit(0);
		}

		String commType = args[0];
		String nbHost = args[1];
		String nbPort = args[2];
		String subTopic = args[3];
		String noOfObservations = args[4];
		String NetworkName = args[5];

		// String commType = "tcp";
		// String nbHost = "gf2.ucs.indiana.edu";
		// String nbPort = "5544";
		// String subTopic = "/SOPAC/GPS/CRTN_01/POS";
		// String noOfObservations = "10";
		//
		String[] argsa = { commType, nbHost, nbPort, subTopic, "" };

		String[] argsb = { noOfObservations, NetworkName };
		RdahmmRunner test = new RdahmmRunner(argsa, argsb);
	}
}

/**
 * 
 * <p>
 * Title: SensorGrid
 * </p>
 * 
 * <p>
 * Description:
 * </p>
 * 
 * <p>
 * Copyright: Copyright (c) 2006
 * </p>
 * 
 * <p>
 * Company:
 * </p>
 * 
 * @author Galip Aydin
 * @version 1.0
 */
class RdahmmDataStruct {
	private String siteName;

	private StringBuffer data;

	private int lineCount;

	private long runcount;

	private int noOfObs;

	private int fwCount;

	private FileWriter fw;

	private String dataDir;

	private String evalDir;

	private String rdahmmshellDir;

	private String plotshellDir;

	private String filePath;

	public RdahmmDataStruct(int noOfObservations, String dataDir_,
			String evalDir_, String rdahmmshellDir_, String plotshellDir_) {
		this.noOfObs = noOfObservations;
		fwCount = 0;
		siteName = "";
		lineCount = 0;
		data = new StringBuffer();
		dataDir = dataDir_;
		evalDir = evalDir_;
		rdahmmshellDir = rdahmmshellDir_;
		plotshellDir = plotshellDir_;
		runcount = 0;
	}

	public void setSiteName(String siteName_) {
		this.siteName = siteName_;
		System.out
				.println("[RdahmmDataStruct] ---> Creating RdahmmDataStruct for "
						+ siteName);
		try {

			if (siteName != null && !siteName.equals("")) {
				File f = new File(dataDir + "/" + siteName);
				if (!f.exists()) {
					f.mkdirs();
				}
				f = new File(evalDir + "/" + siteName);
				if (!f.exists()) {
					f.mkdirs();
				}
				// this.filePath = dataDir + "/" + siteName + "/" + siteName +
				// "_" + getDate(System.currentTimeMillis()) + ".xyz";
				this.filePath = dataDir + "/" + siteName + "/" + siteName
						+ ".xyz";

				fw = new FileWriter(filePath, false);
			}
		} catch (IOException ex) {
			ex.printStackTrace();
		}
	}

	public void setLineCount(int count) {
		this.setLineCount(count);
	}

	public void increaseLineCount() {
		this.lineCount++;
	}

	public void addLine(String line) {
		try {
			data.append(line);
			increaseLineCount();
			fwCount++;
			if (fwCount >= 25 || this.lineCount >= noOfObs) {
				fw.write(data.toString());
				fw.flush();

				fwCount = 0;
				data = new StringBuffer();
			}

			if (this.lineCount >= noOfObs) {
				fw.flush();
				fw.close();
				runRDAHMM(filePath, siteName, evalDir, lineCount);
				runcount++;

				// this.filePath = dataDir + "/" + siteName + "/" + siteName +
				// "_" + getDate(System.currentTimeMillis()) + ".xyz";
				this.filePath = dataDir + "/" + siteName + "/" + siteName
						+ ".xyz";

				fw = new FileWriter(filePath, false);
				this.lineCount = 0;
				this.data = new StringBuffer();
			}
		} catch (IOException ex) {
			ex.printStackTrace();
		}
	}

	public String getSiteName() {
		return siteName;
	}

	public int getLineCount() {
		return this.lineCount;
	}

	public StringBuffer getData() {
		return this.data;
	}

	public String getDate(long timeinms) {
		Calendar cal = Calendar.getInstance();
		cal.setTimeInMillis(timeinms);
		SimpleDateFormat myDateFormat = new SimpleDateFormat(
				"yyyy_MM_dd-hh_mm_ss_a");
		return myDateFormat.format(cal.getTime());
	}

	public void runRDAHMM(String filePath, String siteName, String evalDir,
			int lineCount) {
		System.out.println("[RdahmmFilter] --> Rdahmm Call # " + runcount);
		try {
			System.out.println("[RdahmmFilter] --> Rdahmm Data File = "
					+ filePath);
			String stationName = siteName;
			String command = "";

			// String newfile = evalDir + "/" + stationName + "/" + stationName
			// + "_" + runcount + ".xyz";

			// copy the file
			String DestFileName = evalDir + "/" + stationName + "/" + stationName + ".xyz";
			RdahmmRunner.copyfile(filePath, DestFileName);

			// run rdahmm script.
			command = rdahmmshellDir + " " + DestFileName + " " +"5";
			RdahmmRunner.exec(command);

			// run plot script.
			String xyzFileName = evalDir + "/" + stationName + "/" + stationName + ".xyz.xyz";
			String QFileName = evalDir + "/" + stationName + "/" + stationName + ".Q";
			command = plotshellDir + " " + xyzFileName + " " + QFileName + " ";
			RdahmmRunner.exec(command);

		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}
}
